package edu.neu.ecommerceplatform.service.Impl;

import edu.neu.ecommerceplatform.Exception.ResourceNotFoundException;
import edu.neu.ecommerceplatform.dto.CreateOrderRequest;
import edu.neu.ecommerceplatform.dto.SpenderInfo;
import edu.neu.ecommerceplatform.dto.TopSpenderDto;
import edu.neu.ecommerceplatform.mapper.OrderMapper;
import edu.neu.ecommerceplatform.mapper.UserMapper;
import edu.neu.ecommerceplatform.mapper.DeliverMapper;
import edu.neu.ecommerceplatform.model.Order;
import edu.neu.ecommerceplatform.model.User;
import edu.neu.ecommerceplatform.model.Deliver;
import edu.neu.ecommerceplatform.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    private final OrderMapper orderMapper;
    private final UserMapper userMapper;
    private final DeliverMapper deliverMapper;

    @Autowired
    public OrderServiceImpl(OrderMapper orderMapper, UserMapper userMapper, DeliverMapper deliverMapper) {
        this.orderMapper = orderMapper;
        this.userMapper = userMapper;
        this.deliverMapper = deliverMapper;
    }

    @Override
    public Order getOrderById(Integer id) {
        logger.info("Getting order by id: {}", id);
        Order order = orderMapper.findById(id);
        if (order == null) {
            logger.warn("Order not found with id: {}", id);
            throw new ResourceNotFoundException("Order", "id", id);
        }
        logger.info("Successfully found order with id: {}", id);
        return order;
    }

    @Override
    public List<Order> getAllOrders() {
        logger.info("Getting all orders");
        List<Order> orders = orderMapper.findAll();
        logger.info("Successfully found {} orders", orders.size());
        return orders;
    }

    @Transactional
    @Override
    public Order createOrder(CreateOrderRequest createOrderRequest) {
        logger.info("Creating new order");

        Order order = new Order();
        order.setCustomerId(createOrderRequest.getCustomerId());
        order.setProductId(createOrderRequest.getProductId());
        order.setAddressId(createOrderRequest.getAddressId());
        order.setSubtotalAmount(createOrderRequest.getSubtotalAmount());
        order.setShippingFee(createOrderRequest.getShippingFee());
        order.setDiscountAmount(createOrderRequest.getDiscountAmount());
        order.setTotalAmount(createOrderRequest.getTotalAmount());
        order.setStatus("shipped");
        order.setOrderDate(new Timestamp(System.currentTimeMillis()));

        orderMapper.save(order);
        logger.info("Successfully created order with id: {}", order.getId());

        Deliver deliver = new Deliver();
        deliver.setOrderId(order.getId());
        deliver.setAddressId(order.getAddressId());
        deliver.setCurrentAddress("库房中");
        deliver.setDelivererPhone(null);
        deliverMapper.save(deliver);
        logger.info("Automatically created deliver record for order id: {}", order.getId());

        return order;
    }

    @Transactional
    @Override
    public Order updateOrder(Order order) {
        logger.info("Updating order with id: {}", order.getId());
        Order existingOrder = orderMapper.findById(order.getId());
        if (existingOrder == null) {
            logger.warn("Order not found with id: {}", order.getId());
            throw new ResourceNotFoundException("Order", "id", order.getId());
        }
        orderMapper.update(order);
        logger.info("Successfully updated order with id: {}", order.getId());
        return order;
    }

    @Transactional
    @Override
    public void deleteOrder(Integer id) {
        logger.info("Deleting order with id: {}", id);
        Order existingOrder = orderMapper.findById(id);
        if (existingOrder == null) {
            logger.warn("Order not found with id: {}", id);
            throw new ResourceNotFoundException("Order", "id", id);
        }
        orderMapper.delete(id);
        logger.info("Successfully deleted order with id: {}", id);
    }

    @Override
    public TopSpenderDto getTopSpenderToday() {
        logger.info("Finding the top spending customer for today.");

        SpenderInfo topSpenderInfo = orderMapper.findTopSpenderToday();

        if (topSpenderInfo == null) {
            logger.info("No orders found for today. No top spender.");
            return null;
        }

        Integer topSpenderId = topSpenderInfo.getCustomerId();
        User topUser = userMapper.findById(topSpenderId);
        if (topUser == null) {
            logger.error("Top spender user with ID {} not found, though orders exist.", topSpenderId);
            throw new ResourceNotFoundException("User", "id", topSpenderId);
        }

        String today = LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
        List<Order> orders = orderMapper.findByCustomerIdAndDate(topSpenderId, today);

        TopSpenderDto result = new TopSpenderDto();
        result.setUser(topUser);
        result.setOrders(orders);
        result.setTotalSpentToday(topSpenderInfo.getTotalSpent());

        logger.info("Successfully found top spender of the day: User ID {}", topSpenderId);
        return result;
    }

    @Override
    public List<Order> getOrdersByCustomerId(Integer customerId) {
        logger.info("Getting orders for customer id: {}", customerId);
        return orderMapper.findByCustomerId(customerId);
    }
} 